home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
et
/
et3_0-a1.lha
/
et3
/
src
/
Ink.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-26
|
15KB
|
670 lines
#ifdef __GNUG__
#pragma implementation
#endif
#include "Ink.h"
#include "Class.h"
#include "String.h"
#include "Port.h"
#include "WindowSystem.h"
#include "Math.h"
#include "OrdColl.h"
#include "WindowPort.h"
#include "WindowColorMap.h"
const int MaxWord1= MaxWord+1;
const int cellsz= 8;
const int levels= cellsz*cellsz;
const int cMaxPatterns= 22;
InkManager *gInkManager;
Ink *gInkXor, *gInkNone, *gInkWhite, *gInkBlack, *gHighlightColor;
// obsolete
Ink *ePatXor, *ePatNone, *ePatWhite, *ePatBlack;
static u_short PatBits[cMaxPatterns][8]= {
{ 0x8000,0x0000,0x0800,0x0000,0x8000,0x0000,0x0800,0x0000 },
{ 0x8800,0x0000,0x2200,0x0000,0x8800,0x0000,0x2200,0x0000 },
{ 0xaa00,0x0000,0xaa00,0x0000,0xaa00,0x0000,0xaa00,0x0000 },
{ 0xaa00,0x5500,0xaa00,0x5500,0xaa00,0x5500,0xaa00,0x5500 },
{ 0x5500,0xff00,0x5500,0xff00,0x5500,0xff00,0x5500,0xff00 },
{ 0x7700,0xff00,0xdd00,0xff00,0x7700,0xff00,0xdd00,0xff00 },
{ 0x7f00,0xff00,0xf700,0xff00,0x7f00,0xff00,0xf700,0xff00 },
{ 0x9900,0xCC00,0x6600,0x3300,0x9900,0xCC00,0x6600,0x3300 },
{ 0xff00,0x0000,0xff00,0x0000,0xff00,0x0000,0xff00,0x0000 },
{ 0x5500,0x5500,0x5500,0x5500,0x5500,0x5500,0x5500,0x5500 },
{ 0x4400,0x8800,0x1100,0x2200,0x4400,0x8800,0x1100,0x2200 },
{ 0xbb00,0x7700,0xee00,0xdd00,0xbb00,0x7700,0xee00,0xdd00 },
{ 0xff00,0x0000,0x0000,0x0000,0xff00,0x0000,0x0000,0x0000 },
{ 0x0000,0xff00,0xff00,0xff00,0x0000,0xff00,0xff00,0xff00 },
{ 0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000 },
{ 0xfe00,0xfd00,0xfb00,0xf700,0xef00,0xdf00,0xbf00,0x7f00 },
{ 0x5500,0x8800,0x5500,0x2200,0x5500,0x8800,0x5500,0x2200 },
{ 0xaa00,0x7700,0xaa00,0xdd00,0xaa00,0x7700,0xaa00,0xdd00 },
{ 0x8800,0x8800,0x8800,0x8800,0x8800,0x8800,0x8800,0x8800 },
{ 0xee00,0xee00,0xee00,0xee00,0xee00,0xee00,0xee00,0xee00 },
{ 0xaa00,0x5500,0xaa00,0x5500,0xaa00,0x5500,0xaa00,0x5500 },
{ 0x8000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 }
};
static Bitmap *patterns[cMaxPatterns+1];
static Bitmap **patbms;
static byte *ditherm;
Ink *ePatGrey12, *ePatGrey25, *ePatGrey40, *ePatGrey50;
Ink *ePatGrey60, *ePatGrey75, *ePatGrey87;
Ink *ePat00, *ePat01, *ePat02, *ePat03, *ePat04, *ePat05;
Ink *ePat06, *ePat07, *ePat08, *ePat09, *ePat10, *ePat11;
Ink *ePat12, *ePat13, *ePat14, *ePat15;
//---- Ink ---------------------------------------------------------------------
NewMetaImpl(Ink,Object, (T(id)));
Ink::Ink()
{
id= -1;
}
Ink::Ink(long i)
{
id= i;
}
void Ink::SetId(long i)
{
id= i;
}
void Ink::SetInk(Port *p)
{
p->DevSetOther((int)id);
}
bool Ink::IsEqual(Object *op)
{
return Object::IsEqual(op);
}
OStream& Ink::PrintOn(OStream &s)
{
Object::PrintOn(s);
return s << id SP;
}
IStream& Ink::ReadFrom(IStream &s)
{
Object::ReadFrom(s);
return s >> id;
}
Object *Ink::ReadAndMap(IStream &is)
{
if (IsA() != Meta(Ink))
return Object::ReadAndMap(is);
int id;
Object::ReadFrom(is);
is >> id;
switch (id) {
case -1:
return gInkXor;
case 0:
return gInkNone;
case 1:
return gInkWhite;
case 2:
return gInkBlack;
default:
return new Ink(id);
}
}
//---- InkManager --------------------------------------------------------------
NewMetaImpl(InkManager, Object, (TP(sharedinks)));
InkManager::InkManager()
{
sharedinks= new OrdCollection;
ePatXor= gInkXor= new Ink(-1);
sharedinks->Add(gInkXor);
ePatNone= gInkNone= new Ink((int)0);
sharedinks->Add(gInkNone);
ePatWhite= gInkWhite= new Ink(1);
sharedinks->Add(gInkWhite);
ePatBlack= gInkBlack= new Ink(2);
sharedinks->Add(gInkBlack);
for (int i= 0; i < cMaxPatterns; i++)
patterns[i]= new Bitmap(gPoint8, PatBits[i], 1);
ePatGrey12= patterns[0];
ePatGrey25= patterns[1];
ePatGrey40= patterns[2];
ePatGrey50= patterns[3];
ePatGrey60= patterns[4];
ePatGrey75= patterns[5];
ePatGrey87= patterns[6];
ePat00= patterns[7];
ePat01= patterns[8];
ePat02= patterns[9];
ePat03= patterns[10];
ePat04= patterns[11];
ePat05= patterns[12];
ePat06= patterns[13];
ePat07= patterns[14];
ePat08= patterns[15];
ePat09= patterns[16];
ePat10= patterns[17];
ePat11= patterns[18];
ePat12= patterns[19];
ePat13= patterns[20];
ePat14= patterns[21];
ePat15= patterns[21];
}
InkManager::~InkManager()
{
gInkXor= gInkNone= gInkWhite= gInkBlack= 0;
ePatXor= ePatNone= ePatWhite= ePatBlack= 0;
for (int i= 0; i < cMaxPatterns; i++)
SafeDelete(patterns[i]);
if (patbms) {
for (i= 0; i < levels; i++)
SafeDelete(patbms[i]);
SafeDelete(patbms);
}
SafeDelete(ditherm);
if (sharedinks) {
sharedinks->FreeAll();
SafeDelete(sharedinks);
}
}
bool InkManager::Init()
{
return FALSE;
}
RGBColor *new_RGBColor(short r, short g, short b, short prec)
{
RGBColor *c= new RGBColor(r, g, b, prec);
gInkManager->sharedinks->Add(c);
return c;
}
RGBColor *new_Grey(float graylevel, short prec)
{
RGBColor *c= new RGBColor(graylevel, prec);
gInkManager->sharedinks->Add(c);
return c;
}
//---- RGB ---------------------------------------------------------------------
RGB::RGB(const RGB &c)
{
red= c.red;
green= c.green;
blue= c.blue;
}
RGB::RGB(const HSVColor &hsv)
{
register int i, f, h;
int p, q, t, hue= hsv.hue, saturation= hsv.saturation, value= hsv.value;
if (hue > 359)
hue-= 360;
else if (hue < 0)
hue+= 360;
if (saturation == 0)
red= green= blue= value; // achromatic color: there is no hue
else {
h= hue * MaxWord1 / 60;
i= h / MaxWord1 * MaxWord1;
f= h - i;
p= value * (MaxWord1 - saturation) / MaxWord1;
q= value * (MaxWord1 - (saturation*f)/MaxWord1) / MaxWord1;
t= value * (MaxWord1 - (saturation * (MaxWord1 - f))/MaxWord1) / MaxWord1;
switch (i / MaxWord1) {
case 0:
red= value; green= t; blue= p;
break;
case 1:
red= q; green= value; blue= p;
break;
case 2:
red= p; green= value; blue= t;
break;
case 3:
red= p; green= q; blue= value;
break;
case 4:
red= t; green= p; blue= value;
break;
case 5:
red= value; green= p; blue= q;
break;
}
}
}
RGB::RGB(float graylevel)
{
red= green= blue= (short) (graylevel * MaxWord);
}
void RGB::SetRGB(short r, short g, short b)
{
red= Math::Range((short)0, (short)MaxWord, r);
green= Math::Range((short)0, (short)MaxWord, g);
blue= Math::Range((short)0, (short)MaxWord, b);
}
short RGB::AsGreyLevel()
{
int l= (int) (0.299 * red + 0.587 * green + 0.114 * blue + 0.5);
if (l > MaxWord)
return MaxWord;
return l;
}
OStream& RGB::PrintOn(OStream &os)
{
return os << red SP << green SP << blue SP;
}
IStream& RGB::ReadFrom(IStream &is)
{
return is >> red >> green >> blue;
}
//---- HSVColor ----------------------------------------------------------------
HSVColor::HSVColor(const HSVColor &c)
{
hue= c.hue;
saturation= c.saturation;
value= c.value;
}
HSVColor::HSVColor(RGBColor &rc)
{
RGB rgb(rc.rgb);
int cmax= Math::Max(Math::Max(rgb.red, rgb.green), rgb.blue);
int cmin= Math::Min(Math::Min(rgb.red, rgb.green), rgb.blue);
value= cmax;
if (cmax)
saturation= (cmax - cmin) * MaxWord1 / cmax;
else
saturation= 0;
if (saturation == 0)
hue= 0;
else { // determine hue
int red_distance= (cmax - rgb.red) * MaxWord1 / (cmax - cmin);
int green_distance= (cmax - rgb.green) * MaxWord1 / (cmax - cmin);
int blue_distance= (cmax - rgb.blue) * MaxWord1 / (cmax - cmin);
if (rgb.red == cmax) // resulting color between yellow and magenta
hue= blue_distance - green_distance;
else if (rgb.green == cmax) // resulting color between cyan and yellow
hue= 2*MaxWord1 + red_distance - blue_distance;
else // resulting color between magenta and cyan
hue= 4*MaxWord1 + green_distance - red_distance;
hue= (hue * 60) / MaxWord1; // convert to degrees
if (hue < 0)
hue+= 360; // make nonnegative
else if (hue > 359)
hue-= 360; // make nonnegative
}
}
HSVColor::HSVColor(const RGB &rgb)
{
int cmax= Math::Max(Math::Max(rgb.red, rgb.green), rgb.blue);
int cmin= Math::Min(Math::Min(rgb.red, rgb.green), rgb.blue);
value= cmax;
if (cmax)
saturation= (cmax - cmin) * MaxWord1 / cmax;
else
saturation= 0;
if (saturation == 0)
hue= 0;
else { // determine hue
int red_distance= (cmax - rgb.red) * MaxWord1 / (cmax - cmin);
int green_distance= (cmax - rgb.green) * MaxWord1 / (cmax - cmin);
int blue_distance= (cmax - rgb.blue) * MaxWord1 / (cmax - cmin);
if (rgb.red == cmax) // resulting color between yellow and magenta
hue= blue_distance - green_distance;
else if (rgb.green == cmax) // resulting color between cyan and yellow
hue= 2*MaxWord1 + red_distance - blue_distance;
else // resulting color between magenta and cyan
hue= 4*MaxWord1 + green_distance - red_distance;
hue= (hue * 60) / MaxWord1; // convert to degrees
if (hue < 0)
hue+= 360; // make nonnegative
else if (hue > 359)
hue-= 360; // make nonnegative
}
}
OStream &HSVColor::PrintOn(OStream &s)
{
return s << hue SP << saturation SP << value SP;
}
IStream &HSVColor::ReadFrom(IStream &s)
{
return s >> hue >> saturation >> value;
}
//---- ColorMap ----------------------------------------------------------------
ColorMap::ColorMap(int sz)
{
size= 0;
map= 0;
Expand(sz);
}
ColorMap::ColorMap(ColorMap *cmap)
{
size= 0;
map= 0;
Expand(cmap->size);
for (int i= 0; i < size; i++)
map[i]= cmap->map[i];
}
ColorMap::~ColorMap()
{
SafeDelete(map);
}
void ColorMap::Expand(int sz)
{
if (sz > size) {
map= (RGB*) Realloc(map, sz*sizeof(RGB));
size= sz;
}
}
void ColorMap::SetEntry(int ix, RGB &rgb)
{
Expand(ix+1);
map[ix]= rgb;
}
RGB ColorMap::GetEntry(int ix)
{
Expand(ix+1);
return map[ix];
}
OStream& ColorMap::PrintOn(OStream &os)
{
os << size;
if (size > 0) {
for (int i= 0; i < size; i++) {
if ((i % 8) == 0)
os NL;
os << map[i];
}
}
return os NL;
}
IStream& ColorMap::ReadFrom(IStream &is)
{
is >> size;
if (size > 0) {
Expand(size);
for (int i= 0; i < size; i++)
is >> map[i];
}
return is;
}
bool ColorMap::IsGrey()
{
for (int i= 0; i < size; i++)
if (! map[i].IsGrey())
return FALSE;
return TRUE;
}
//---- RGBColor ----------------------------------------------------------------
NewMetaImpl(RGBColor,Ink, (T(prec)));
RGBColor::RGBColor() : rgb((short)0), Ink(-1)
{
SetFlag(eInkChanged);
prec= 0;
port= 0;
}
RGBColor::RGBColor(RGBColor *cp) : Ink(-1)
{
SetFlag(eInkChanged);
if (cp) {
rgb= cp->rgb;
prec= cp->prec;
}
port= 0;
}
RGBColor::RGBColor(short r, short g, short b, short p) : rgb(r,g,b), Ink(-1)
{
SetFlag(eInkChanged);
prec= p;
port= 0;
}
RGBColor::RGBColor(short graylevel, short p) : rgb(graylevel), Ink(-1)
{
SetFlag(eInkChanged);
prec= p;
port= 0;
}
RGBColor::RGBColor(float graylevel, short p) : rgb(graylevel), Ink(-1)
{
SetFlag(eInkChanged);
prec= p;
port= 0;
}
RGBColor::RGBColor(const RGB &c, short p) : rgb(c), Ink(-1)
{
SetFlag(eInkChanged);
prec= p;
port= 0;
}
RGBColor::RGBColor(const HSVColor &hsv, short p) : rgb(hsv), Ink(-1)
{
SetFlag(eInkChanged);
prec= p;
port= 0;
}
RGBColor::RGBColor(const RGBColor &rc) : rgb(rc.rgb), Ink(-1)
{
SetFlag(eInkChanged);
prec= 0;
port= 0;
}
bool RGBColor::SetRGB(RGB *c, short p)
{
bool rc= TRUE;
rgb= *c;
prec= Math::Range((short)0, (short)MaxWord, p);
SetFlag(eInkChanged);
if (prec == MaxWord && port) {
WindowPort *wport= (WindowPort*)port;
int newid= (int) wport->ColorMap()->AllocateAndSetCell(GetId(), c, wport);
ResetFlag(eInkChanged);
if (newid == GetId())
rc= FALSE;
SetId(newid);
}
Changed();
return rc;
}
bool RGBColor::SetHSV(short hue, short sat, short value, short p)
{
HSVColor hc(hue, sat, value);
RGB rc(hc);
return SetRGB(&rc, p);
}
bool RGBColor::SetRGB(short r, short g, short b, short p)
{
RGB rc(r, g, b);
return SetRGB(&rc, p);
}
void RGBColor::SetInk(Port *p)
{
port= p;
p->SetColor(this);
}
OStream &RGBColor::PrintOn(OStream &s)
{
Object::PrintOn(s);
return s << rgb << prec SP;
}
IStream &RGBColor::ReadFrom(IStream &s)
{
Object::ReadFrom(s);
SetFlag(eInkChanged);
SetId(-1);
port= 0;
s >> rgb >> prec;
prec= 0;
return s;
}
Object *RGBColor::ReadAndMap(IStream &is)
{
return Object::ReadAndMap(is);
}
//---- RGBColorCell ------------------------------------------------------------
NewMetaImpl0(RGBColorCell,RGBColor);
RGBColorCell::RGBColorCell(int i)
{
SetId(i);
ResetFlag(eInkChanged);
}
void RGBColorCell::SetInk(Port *p)
{
port= p;
ResetFlag(eInkChanged);
p->SetColor(this);
}
OStream& RGBColorCell::PrintOn(OStream &os)
{
Object::PrintOn(os);
return os << GetId() SP;
}
IStream& RGBColorCell::ReadFrom(IStream &is)
{
int i;
Object::ReadFrom(is);
is >> i;
SetId(i);
return is;
}
Object *RGBColorCell::ReadAndMap(IStream &is)
{
return Object::ReadAndMap(is);
}
//---- halftoning --------------------------------------------------------------
static void dither(int s, byte *m, int x, int y, int n);
static void dither4(int s, byte *m, int x, int y, int n, int d)
{
if (n > 1) {
register int i, j;
dither(s, m, x, y, n);
for (i= x; i < x+n; i++)
for (j= y; j < y+n; j++)
m[i*s+j]= m[i*s+j]*4+d;
} else
m[x*s+y]= d;
}
static void dither(int s, byte *m, int x, int y, int n)
{
int n2= n/2;
dither4(s, m, x, y, n2, 0);
dither4(s, m, x+n2, y+n2, n2, 1);
dither4(s, m, x+n2, y, n2, 2);
dither4(s, m, x, y+n2, n2, 3);
}
Ink *Grey2Halftone(float f)
{
int level;
if (f < 0)
f= 0.0;
else if (f > 1.0)
f= 1.0;
f= 1.0 - f;
level= (int)(f * levels + 0.5);
if (level <= 0)
return gInkWhite;
if (level >= levels)
return gInkBlack;
if (patbms == 0) {
patbms= new Bitmap* [levels];
ditherm= new byte[levels];
dither(cellsz, ditherm, 0, 0, cellsz);
}
if (patbms[level] == 0) {
Bitmap *bm= patbms[level]= new Bitmap(cellsz, 0, 1);
for (int y= 0; y < cellsz; y++) {
for (int x= 0; x < cellsz; x++)
if (level > ditherm[x*cellsz+y])
bm->SetPixel(x, y, 1);
else
bm->SetPixel(x, y, 0);
}
}
return patbms[level];
}